1 /***
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Exoffice Technologies. For written permission,
18 * please contact info@exolab.org.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Exoffice Technologies. Exolab is a registered
23 * trademark of Exoffice Technologies.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 2004-2005 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * $Id: ManagedConnectionHandle.java,v 1.8 2006/12/16 12:37:17 tanderson Exp $
44 */
45 package org.exolab.jms.net.connector;
46
47 import org.exolab.jms.net.uri.URI;
48
49 import java.security.Principal;
50
51
52 /***
53 * A handle to a {@link ManagedConnection} that tracks its utilisation.
54 *
55 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
56 * @version $Revision: 1.8 $ $Date: 2006/12/16 12:37:17 $
57 */
58 final class ManagedConnectionHandle implements ManagedConnection {
59
60 /***
61 * The connection pool that owns this.
62 */
63 private final DefaultConnectionPool _pool;
64
65 /***
66 * The connection to delegate all requests to.
67 */
68 private final ManagedConnection _connection;
69
70 /***
71 * The connection factory for resolving connections via their URI.
72 */
73 private final ConnectionFactory _resolver;
74
75 /***
76 * The no. of active ConnectionHandle instances.
77 */
78 private int _connectionCount = 0;
79
80 /***
81 * Determines if the connection has been since {@link #clearUsed} was
82 * last invoked.
83 */
84 private boolean _used = false;
85
86 /***
87 * Determines if a ping is in progress.
88 */
89 private boolean _pinging = false;
90
91 /***
92 * The no. of times {@link #incPingWaits} has been invoked since the last
93 * {@link #ping}.
94 */
95 private int _pingWaits;
96
97
98 /***
99 * Construct a new <code>ManagedConnectionHandle</code>.
100 *
101 * @param pool the pool that owns this
102 * @param connection the connection to delegate requests to
103 * @param resolver the connection factory for resolving connections via
104 * their URI.
105 */
106 public ManagedConnectionHandle(DefaultConnectionPool pool,
107 ManagedConnection connection,
108 ConnectionFactory resolver) {
109 _pool = pool;
110 _connection = connection;
111 _resolver = resolver;
112 }
113
114 /***
115 * Registers a handler for handling invocations on objects exported via this
116 * connection. Once a handler is registered, it cannot be de-registered.
117 *
118 * @param handler the invocation handler
119 * @throws IllegalStateException if a handler is already registered
120 * @throws ResourceException for any error
121 */
122 public void setInvocationHandler(InvocationHandler handler)
123 throws ResourceException {
124 _connection.setInvocationHandler(handler);
125 }
126
127 /***
128 * Registers a connection event listener.
129 *
130 * @param listener the connection event listener
131 * @throws ResourceException for any error
132 */
133 public void setConnectionEventListener(ManagedConnectionListener listener)
134 throws ResourceException {
135 _connection.setConnectionEventListener(listener);
136 }
137
138 /***
139 * Creates a new connection handle for the underlying physical connection.
140 *
141 * @return a new connection handle
142 * @throws IllegalStateException if an <code>InvocationHandler</code> hasn't
143 * been registered
144 * @throws ResourceException for any error
145 */
146 public Connection getConnection() throws ResourceException {
147 Connection connection = _connection.getConnection();
148 return new ConnectionHandle(connection);
149 }
150
151 /***
152 * Ping the connection. The connection event listener will be notified
153 * if the ping succeeds.
154 *
155 * @throws ResourceException for any error
156 */
157 public synchronized void ping() throws ResourceException {
158 try {
159 _pinging = true;
160 _pingWaits = 0;
161 _connection.ping();
162 } catch (ResourceException exception) {
163 _pinging = false;
164 throw exception;
165 }
166 }
167
168 /***
169 * Determines if a ping has been sent.
170 *
171 * @return <code>true</code> if a ping has been sent
172 */
173 public synchronized boolean pinging() {
174 return _pinging;
175 }
176
177 /***
178 * Notifies of a ping response.
179 * Clears the ping status, and resets the ping wait to <code>0</code>.
180 */
181 public synchronized void pinged() {
182 _pinging = false;
183 _pingWaits = 0;
184 }
185
186 /***
187 * Increments the no. of times this connection has waited for a ping
188 * response.
189 *
190 * @return the no. of times this connection has waited for a ping response
191 */
192 public synchronized int incPingWaits() {
193 return ++_pingWaits;
194 }
195
196 /***
197 * Returns the remote address to which this is connected.
198 *
199 * @return the remote address to which this is connected
200 * @throws ResourceException for any error
201 */
202 public URI getRemoteURI() throws ResourceException {
203 return _connection.getRemoteURI();
204 }
205
206 /***
207 * Returns the local address that this connection is bound to.
208 *
209 * @return the local address that this connection is bound to
210 * @throws ResourceException for any error
211 */
212 public URI getLocalURI() throws ResourceException {
213 return _connection.getLocalURI();
214 }
215
216 /***
217 * Returns the principal associated with this connection.
218 *
219 * @return the principal associated with this connection,
220 * or <code>null<code> if none is set
221 * @throws ResourceException for any error
222 */
223 public Principal getPrincipal() throws ResourceException {
224 return _connection.getPrincipal();
225 }
226
227 /***
228 * Destroys the physical connection.
229 *
230 * @throws ResourceException for any error
231 */
232 public void destroy() throws ResourceException {
233 _connection.destroy();
234 }
235
236 /***
237 * Marks the connection as being used.
238 */
239 public synchronized void setUsed() {
240 _used = true;
241 }
242
243 /***
244 * Determines if the connection has been used since {@link #clearUsed}
245 * was last invoked.
246 */
247 public synchronized boolean used() {
248 return _used;
249 }
250
251 /***
252 * Marks the connection as being unused.
253 */
254 public synchronized void clearUsed() {
255 _used = false;
256 }
257
258 /***
259 * Determines if the connection can be destroyed. The connection
260 * can be destroyed if there are no associated {@link Connection} instances,
261 * and it has been used since {@link #clearUsed} was invoked.
262 *
263 * @return <code>true</code> if the connection may be destroyed
264 */
265 public synchronized boolean canDestroy() {
266 return (_connectionCount == 0) && (!_used);
267 }
268
269 /***
270 * Increment the no. of references to this connection.
271 */
272 private synchronized void incActiveConnections() {
273 ++_connectionCount;
274 }
275
276 /***
277 * Decrement the no. of references to this connection.
278 */
279 private synchronized void decActiveConnections() {
280 --_connectionCount;
281 if (_connectionCount <= 0) {
282 _pool.idle(this);
283 }
284 }
285
286 public boolean usedSinceLastPing() {
287 return false;
288 }
289
290 /***
291 * Helper class reference count a {@link Connection} instance.
292 */
293 private class ConnectionHandle implements Connection {
294
295 /***
296 * The connection to delegate all requests to.
297 */
298 private Connection _connection;
299
300 /***
301 * Construct a new <code>ConnectionHandle</code>.
302 *
303 * @param connection the connection to delegate requests to
304 */
305 public ConnectionHandle(Connection connection) {
306 _connection = connection;
307 incActiveConnections();
308 }
309
310 /***
311 * Invoke a method on a remote object.
312 *
313 * @param request the request
314 * @return the result of the invocation
315 * @throws Throwable for any transport error
316 */
317 public Response invoke(Request request) throws Throwable {
318 Response response = null;
319 setUsed();
320 try {
321 ConnectionContext.push(getPrincipal(), _resolver);
322 response = _connection.invoke(request);
323 } finally {
324 ConnectionContext.pop();
325 }
326 return response;
327 }
328
329 /***
330 * Returns the remote address to which this is connected.
331 *
332 * @return the remote address to which this is connected
333 * @throws ResourceException for any error
334 */
335 public URI getRemoteURI() throws ResourceException {
336 return _connection.getRemoteURI();
337 }
338
339 /***
340 * Returns the local address that this connection is bound to.
341 *
342 * @return the local address that this connection is bound to
343 * @throws ResourceException for any error
344 */
345 public URI getLocalURI() throws ResourceException {
346 return _connection.getLocalURI();
347 }
348
349 /***
350 * Close this connection, releasing any allocated resources.
351 *
352 * @throws ResourceException for any error.
353 */
354 public void close() throws ResourceException {
355 try {
356 _connection.close();
357 } finally {
358 _connection = null;
359 decActiveConnections();
360 }
361 }
362
363 /***
364 * Called by the garbage collector when there are no more references to
365 * the object.
366 */
367 protected void finalize() throws Throwable {
368 if (_connection != null) {
369 decActiveConnections();
370 }
371 super.finalize();
372 }
373 }
374 }